package biblioGraphiqueV2;

import java.io.Serializable;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.LinkedList;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
 * Classe controleur et application (système)
 * @author IUT,   Frederic Blanc, Anthony Pierro, Louis Amore, Johanna Loville
 * @version 1.0 
 */


public class Controleur implements Serializable{
	
	private static final long serialVersionUID = 1L;

	/**
	 * La classe Controleur est unique pour tous les cas d'utilisation
	 * Elle est également la classe "application" qui gère l'ensemble des objets de l'appli
	 */	
	// ************************************************************************************************************
		// Attributs
		// ************************************************************************************************************
		private Quota quota;
		// Attributs d'Association
		// Ensemble des ouvrages de la bibliothèque
		private HashMap<String, Ouvrage> 		_ouvrages;
		private HashMap<String, Lecteur> 		lecteurs; 
		private HashMap<String, Auteur>  		auteurs;
		private HashMap<String, Periodique> 	periodiques;
		private HashMap<Integer, Reservation> 	reservations;
		private HashMap<Integer, Emprunt> 		emprunts;
		// la liste des vues. La 1ere est toujours la vue Menu Principal. La dernière est la vue active.
		private LinkedList<Vue> _vues;
		
		
		
		// ************************************************************************************************************
		// Constructeur
		// ************************************************************************************************************

		public Controleur() {
			this.setOuvrages(new HashMap<String, Ouvrage>());
			this.setAuteurs(new HashMap<String, Auteur>());
			this.setLecteurs(new HashMap<String, Lecteur>());
			this.setPeriodiques(new HashMap<String, Periodique>());
			this.setReservations(new HashMap<Integer, Reservation>());
			this.setEmprunts(new HashMap<Integer, Emprunt>());
			Quota q = new Quota();
			this.setquota(q);
			_vues = new LinkedList<Vue>();
		} // Fin Controleur

		// ************************************************************************************************************
		// Méthodes privées
		// ************************************************************************************************************

		// ------------------------------------------------------------------------------------------------------------
		// Affecteurs
		/**
		 * setter du quota
		 * @param Q
		 */
		private void setquota(Quota Q){
			quota = Q;
		}
		/**
		 * Ajoute un ouvrage à l'ensemble des ouvrages de la bibliothèque.
		 * @param ouvrage 	Ouvrage à ajouter
		 * @param isbn 	code ISBN de cet ouvrage
		 */
		private void setOuvrage(Ouvrage ouvrage, String isbn) {
			this.getOuvrages().put(isbn, ouvrage);
		} // Fin setOuvrage

		/**
		 * Ajoute un auteur à l'ensemble des auteurs de la bibliothèque.
		 * @param aut
		 * @param nomPrenom
		 */
		private void setAuteur(Auteur aut, String nomPrenom) {
			this.getAuteurs().put(nomPrenom, aut);
		} 
		
		private void setPeriodique(Periodique p, String issn) {
			this.getPeriodiques().put(issn, p);
		} 
		
		private void setLecteur(Lecteur lecteur, String numLecteur){
			this.getLecteurs().put(numLecteur, lecteur);
		}
		
		private void setLecteur(HashMap<String, Lecteur> lecteur) {
			this.lecteurs = lecteur;
		}
		
		private void setReservation(Reservation res, int d){
			this.getReservations().put(d, res);
		}
		
		private void setEmprunt(Emprunt emprunt, int id) {
			this.getEmprunts().put(id, emprunt);
		}
		
		/**
		 * @param ouvrages hashtable d'ouvrages à affecter
		 */
		private void setOuvrages(HashMap<String, Ouvrage> ouvrages) {
			_ouvrages = ouvrages;
		}// Fin setOuvrages
		
		private void setReservations(HashMap<Integer, Reservation> res){
			reservations = res;
		}
		
		private void setLecteurs(HashMap<String, Lecteur> lecteurs){
			this.lecteurs = lecteurs;
		}
		
		/**
		 * @param auteurs hashtable d'auteurs
		 */
		private void setAuteurs(HashMap<String, Auteur> auteurs) {
			this.auteurs = auteurs;
		}
		
		private void setPeriodiques(HashMap<String, Periodique> periodiques) {
			this.periodiques = periodiques;
		}
		
		private void setEmprunts(HashMap<Integer, Emprunt> emprunts) {
			this.emprunts = emprunts;
		}
		/**
		 * ajoute ou enlève la vue active courante de la liste des vues
		 * @param vue  la vue à affecter
		 */
		 private void setVue(Vue vue) {
				_vues.addLast(vue);
		 }
		 private void removeVue() {
				_vues.removeLast();
		 }
		
		/*
		// ------------------------------------------------------------------------------------------------------------
		// Accesseurs
		
		/**
		 * @return ensemble des ouvrages de la bibliothèque
		 */
		public HashMap<String, Ouvrage> getOuvrages() {
			return _ouvrages;
		}// Fin getOuvrages

		/**
		 * Dictionnaire d'auteurs
		 * @return ensemble d'auteurs
		 */
		public HashMap<String, Auteur> getAuteurs() {
			return auteurs;
		}
		public Quota getQuota()
		{
			return quota;
		}
		
		public HashMap<Integer, Reservation> getReservations() {
			return reservations;
		}
		
		
		public HashMap<String, Periodique> getPeriodiques() {
			return periodiques;
		}
		
		public HashMap<String, Lecteur> getLecteurs() {
			return lecteurs;
		}
		
		public HashMap<Integer, Emprunt> getEmprunts() {
			return emprunts;
		}
		
		/**
		 * Accès à un ouvrage par son numéro ISBN
		 * @param isbn 	le code ISBN de l'ouvrage cherché
		 * @return l'ouvrage qui a l'ISBN indiqué
		 */
		private Ouvrage getOuvrage(String isbn) {
			return this.getOuvrages().get(isbn);
		} // Fin getOuvrage
		
		/**
		 * Accès à un auteur par la concaténation du nom+prénom
		 * @param nomPrenom
		 * @return l'auteur correspondant
		 */
		public Auteur getAuteur(String nomPrenom) {
			return this.getAuteurs().get(nomPrenom);
		}

		private Periodique getPeriodique(String issn) {
			return this.getPeriodiques().get(issn);
		}
		private Lecteur getLecteur(String numLecteur) {
			return this.getLecteurs().get(numLecteur);
		}
		private Reservation getReservation(int num) {
			return this.getReservations().get(num);
		}
		
		
		/**
		 * @return la vue active courante 
		 */
		private Vue getVue() {
			return (Vue)_vues.getLast() ;
		}
		/**
		 * @return la vue Menu Principal 
		 */
		private VueMenuBiblio getVueMenu() {
			return (VueMenuBiblio)_vues.getFirst() ;
		}
		
		/*
		// ************************************************************************************************************
		// Méthodes publiques de création et affichage des fenêtres de l'application et fermeture
		// ************************************************************************************************************
		/**
		 * Création et affichage de la fenêtre principale de l'application. 
		 * Elle propose le menu de l'appli
		 */
		
		public void menuBiblio() {
			try {this.setVue(new VueMenuBiblio(this));
				this.getVueMenu().setVisible(true); 	
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		/**
		 * Cas d'utilisation : consultation d'un ouvrage
		 * Création et affichage de la fenêtre de consultation d'un ouvrage
		 */
		
		public void consulterOuvrage() {
			try {this.setVue (new VueConsultOuvrage(this));
			// le Menu est caché
				this.getVueMenu().setVisible(false); 	
			// la vue courante est VueConsultOuvrage
				this.getVue().setEtat(Vue.initiale);
				this.getVue().setVisible(true);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		/** Frédéric Blanc : CU1 - Parametrage des quotas
		 * Permet de fixer le nombre maximum d'emprunts ou de réservations pouvant 
		 * être effectués pas un lecteur, la durée d'un emprunt, le montant de
		 * la pénalité journalière pour retard, la durée de validité d'une réservation
		 * 
		 * - Achever et Operationnel -
		 */
		public void parametrerQuotas()
		{
			try{
					this.setVue(new VueParametrerQuotas(this)); 
					this.getVueMenu().setVisible(false); // Menu Caché
					this.getVue().setEtat(Vue.initiale); // Nouvelle vue courante
					this.getVue().setVisible(true);
			}
			catch(Exception err){
				err.printStackTrace();
			}
		}		
		
		
		/** Johanna Loville : CU2 - Recherche par auteur
		 * A partir des nom et prénom de l'auteur, l'ensemble des documents
		 * de cet auteur présents en bibliothèque est affiché avec toutes les informations
		 * permettant de retrouver les documents.
		 */
		public void rechercherParAuteur() {
			if (getAuteurs().size() == 0) {
				Message dialog = new Message ("Aucun auteur enregistré");
			}
			else{
				try {
					this.setVue(new VueRechercherParAuteur(this));
					this.getVueMenu().setVisible(false); //Menu Caché
					this.getVue().setEtat(Vue.initiale); //Nouvelle Vue courante
					this.getVue().setVisible(true);
				}
				catch(Exception err){
					err.printStackTrace();
				}
			}
		}
			
		/** Anthony Pierro : CU3 - Nouveau Périodique
		 * Le périodique est enregistré avec toutes avec toutes ses informations.
		 */
		public void nouveauPeriodique()
		{
			try{
					this.setVue(new VueSaisiePeriodique(this)); 
					this.getVueMenu().setVisible(false); // Menu Caché
					this.getVue().setEtat(Vue.initiale); // Nouvelle vue courante
					this.getVue().setVisible(true);
			}
			catch(Exception err){
				err.printStackTrace();
			}
		}
		
		/** Anthony Pierro : CU4 - Nouvelle Parution
		 * La parution d'un périodique est enregistrée avec ses articles.
		 */
		public void nouvelleParution()
		{
			try{
					this.setVue(new VueSaisieParution(this, auteurs)); 
					this.getVueMenu().setVisible(false); // Menu Caché
					this.getVue().setEtat(Vue.initiale); // Nouvelle vue courante
					this.getVue().setVisible(true);
			}
			catch(Exception err){
				err.printStackTrace();
			}
		}
		
		/** Anthony Pierro : CU5 - Consultation d'un périodique
		 * Les informations relatives au périodique sont affichées (avec le nombre de parutions reçues).
		 */
		public void consulterPeriodique()
		{
			try{
					this.setVue(new VueConsultPeriodique(this)); 
					this.getVueMenu().setVisible(false); // Menu Caché
					this.getVue().setEtat(Vue.initiale); // Nouvelle vue courante
					this.getVue().setVisible(true);
			}
			catch(Exception err){
				err.printStackTrace();
			}
		}
		
		/** Johanna Loville : CU6 - Nouveau lecteur
		 * Les informations relatives au nouveau lecteur sont enregistrées
		 */
		public void saisirLecteur() {
			try {
				this.setVue(new VueSaisieLecteur(this));
				// le Menu est caché
					this.getVueMenu().setVisible(false);
				// la vue courante es VueSaisieLecteur
					this.getVue().setEtat(Vue.initiale);
					this.getVue().setVisible(true);
			}
			catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		/** Johanna Loville : CU7 - Consultation d'un lecteur
		 * On veut connaître toutes les informations le concernant 
		 * avec en particulier celles concernant ses emprunts et réservations en cours
		 */
		public void consulterLecteur() {
			if (getLecteurs().size() == 0) {
				Message dialog = new Message("Aucun lecteur enregistré");
			}
			else {
				try {
					this.setVue(new VueConsulterLecteur(this));
					this.getVueMenu().setVisible(false);
					this.getVue().setEtat(Vue.initiale);
					this.getVue().setVisible(true);
				}
				catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		
		/** Louis Amore : CU8 - Emprunt d'un exemplaire
		 * L'emprunt d'un exemplaire empruntable et disponible, (par un lecteur n'ayant pas atteint le quota maximum
		 * d'emprunt et pour lequel aucun des emprunts en cours n'accuse de retard) est enregistré.
		 */
		public void empruntExemplaire()
		{
			try{
					this.setVue(new VueEmpruntExemplaire(this)); 
					this.getVueMenu().setVisible(false); // Menu Caché
					this.getVue().setEtat(Vue.initiale); // Nouvelle vue courante
					this.getVue().setVisible(true);
			}
			catch(Exception err){
				err.printStackTrace();
			}
		}
		
		
		/** Louis Amore : CU9 - Retour d'un exemplaire
		 * Le retour d'un exemplaire emprunté par un lecteur est enregistré. En cas de retard,
		 * une pénalité par jour de retard est appliquée. L'emprunt est supprimé.
		 */
		public void retourExemplaire()
		{
			try{
					this.setVue(new VueRetourExemplaire(this)); 
					this.getVueMenu().setVisible(false); // Menu Caché
					this.getVue().setEtat(Vue.initiale); // Nouvelle vue courante
					this.getVue().setVisible(true);
			}
			catch(Exception err){
				err.printStackTrace();
			}
		}
		
		/** Frédéric Blanc : CU10 - Reservation d'un ouvrage
		 * La réservation d’un exemplaire d’un ouvrage est
		 * enregistrée. Un lecteur est limité dans son nombre de réservations.
		 * De plus, pour réserver il ne doit pas avoir de retard dans ses emprunts.
		 * Parmi les exemplaires empruntés de l’ouvrage qui intéresse le lecteur,
		 * le système choisit celui avec la date de retour prévue la plus proche
		 * et le réserve. Dans tous les cas, la réservation est valable pour une durée
		 * limitée après la date de retour prévue de l’exemplaire.
		 * - Achevé et Operationnel -
		 */
		public void reservationOuvrage(){
			Message Dialog;
			try{
				
				if(getOuvrages().size() == 0)
				{
					 Dialog = new Message("Aucun ouvrage n'est enregistré");
				}
				else if(lecteurs.size() == 0)
				{
					Dialog = new Message("Aucun lecteur n'est enregistré");
				}
				else if(quota == null){
					 Dialog = new Message("Aucun quota enregistré");
					 
				}
				else
				{			
					this.setVue(new VueResOuvrage(this));
					this.getVueMenu().setVisible(false); // Menu Caché
					this.getVue().setEtat(Vue.initiale); // Nouvelle vue courante
					this.getVue().setVisible(true);
				}
			}
			catch(Exception err){
				err.printStackTrace();
					Dialog = new Message("Un problème est survenu lors de la réservation");
			}
		}
		
		
		/** Louis Amore : CU11 - Retour d'un exemplaire réservé
		 * Le lecteur vient emprunter l'ouvrage qu'il a réservé. La bibliothécaire, après avoir recherché l'exemplaire effectivement 
		 * réservé par le lecteur, procède à l'enregistrement de l'emprunt. La trace de la réservation n'est pas concervée. 
		 * 
		 */
		public void empruntExemplaireReserve()
		{
			try{
					this.setVue(new VueEmpruntExemplaireReserve(this)); 
					this.getVueMenu().setVisible(false); // Menu Caché
					this.getVue().setEtat(Vue.initiale); // Nouvelle vue courante
					this.getVue().setVisible(true);
			}
			catch(Exception err){
				err.printStackTrace();
			}
		}
		
		/** Frédéric Blanc : CU12 - Suppression Reservation perimé.
		 * Les réservations dont le délai est dépassé sont automatiquement supprimées.
		 * - Achevé et Operationnel -
		 */
		public void suprimerRes() {
			Message dialog; 
			getReservations();
			int j = 0;
			if(reservations.size() != 0)
			{
			for (int i : getReservations().keySet()) {
				Reservation r = getReservations().get(i);
				if (r.getDateDebut().compareTo(r.getDateLimite()) < 0) {
					reservations.remove(i);
					j++;
				}
			}
			if(j == 0){
				dialog = new Message("Aucune réservation à supprimer");
			}
			else{
				dialog = new Message("Les réservations périmées ont été supprimées");
			}
			
			}
			else
				dialog = new Message("Aucune réservation d'enregistrée");
		}
		
		
		/**
		 * Cas d'utilisation : saisie d'un exemplaire d'ouvrage
		 * Création et affichage de la fenêtre de saisie d'un exemplaire d'ouvrage
		 */
		public void saisirExemplaire() {
			try {this.setVue(new VueSaisieExemplaire(this));
			// le Menu est caché
				this.getVueMenu().setVisible(false); 
			// la vue courante est VueSaisieExemplaire
				this.getVue().setEtat(Vue.initiale);
				this.getVue().setVisible(true);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		/**
		 * cas d'utilisation : saisie d'un ouvrage
		 * Création et affichage de la fenêtre de saisie d'un ouvrage
		 */
		public void saisirOuvrage() {
			try {this.setVue(new VueSaisieOuvrage(this));
			// le Menu est caché
				this.getVueMenu().setVisible(false); 
			// la vue courante est VueSaisieOuvrage
				this.getVue().setEtat(Vue.initiale);
				this.getVue().setVisible(true);
			} catch (Exception e) {
			e.printStackTrace();
			}
		}
		/**
		 * fermeture de la fenêtre vue
		 * lors de la fermeture de la fenêtre principale de l'application sauvegarde des objets sérialisés 
		 */
		public void fermerVue (Vue vue) {
			//la vue est détruite et n'est plus la vue active courante	
			
			if (vue instanceof VueMenuBiblio ) {
			// Quitte l'aplication. Sauvegarde les objets du modèle
				vue.dispose();
				this.removeVue();this.sauve();
				System.exit(0);
				}
			else {
			// le Menu est rendu de nouveau visible
				vue.dispose();
				this.removeVue();
				this.getVueMenu().setVisible(true); 
			}
		}
		
		/*
		// ************************************************************************************************************
		// Opérations liées à la sérialisation des objets de l'application
		// ************************************************************************************************************
		/** ConsultPeriodique
		 *  restauration des objets de l'application
		 */
		public Controleur restaure() {
			try {
				FileInputStream fichier = new FileInputStream("Fsauv.ser");
				ObjectInputStream in = new ObjectInputStream(fichier);
				return((Controleur) in.readObject());
			} catch (Exception e) {
				Message dialog = new Message("Problème de restauration ou fichier non encore créé");
				return this;
			} 
		}
		/**
		 *  sauvegarde des objets de l'application
		 */
		private void sauve() {
			try {
				FileOutputStream f = new FileOutputStream("Fsauv.ser");
				ObjectOutputStream out = new ObjectOutputStream(f);
				out.writeObject(this);
			} catch (Exception e) {
				Message dialog = new Message("Problème de sauvegarde dans le fichier");
			}
		}
		// ************************************************************************************************************
		// Opérations liées à l'application en réponse à une action de l'utilisateur dans une vue
		// ************************************************************************************************************

		/**
		 * Accès à un ouvrage par son numéro ISBN
		 * Invoqué dans VueConsultOuvrage et VueSaisieExemplaire
		 * @param isbn 	le code ISBN de l'ouvrage cherché
		 * @return l'ouvrage qui a l'ISBN indiqué ou null
		 * affiche un message d'erreur si l'ouvrage n'est pas trouvéssss
		 */
		public Ouvrage rechOuvrage(String isbn) {
			Ouvrage ouv = this.getOuvrage(isbn);
			if (ouv == null) {
				Message dialog = new Message("Ouvrage inconnu");
			}
			else {
				// la vue courante est VueSaisieExemplaire
				if (this.getVue() instanceof VueSaisieExemplaire){
				// la vue est inscrite comme observatrice de l'ouvrage	
					ouv.addObserver(this.getVue());
				// le contrôleur modifie l'état de la vue
					this.getVue().setEtat(Vue.inter1);	
				// le controleur demande à la vue d'afficher les infos de l'ouvrage
					((VueSaisieExemplaire)this.getVue()).alimente(ouv);
					}
				// la vue courante est VueConsultOuvrage
				if (this.getVue() instanceof VueConsultOuvrage){
					// le contrôleur modifie l'état de la vue
					this.getVue().setEtat(Vue.finale);
					((VueConsultOuvrage)this.getVue()).alimente(ouv);
					}
			}
			return ouv;
		} // Fin rechOuvrage
		
		/**
		 * methode pour retrouver le lecteur (Fait dans le cadre de la CU10 & CU8 par Frederic Blanc)
		 * @return
		 */		
		public void rechPeriodique(String issn){
			Message dialog;
			if (this.getVue() instanceof VueSaisieParution){
				if(getPeriodique(issn)==null){
					 dialog = new Message("Le périodique n'existe pas");
				}
				else
					this.getVue().setEtat(Vue.inter1);
			}
			if (this.getVue() instanceof VueConsultPeriodique){
				if(getPeriodique(issn)==null){
					 dialog = new Message("Le périodique n'existe pas");
				}
				else {
					Periodique p = this.getPeriodique(issn);
					((VueConsultPeriodique)this.getVue()).alimente(p.getTitre(), p.getNbrParution());
					this.getVue().setEtat(Vue.inter1);
				}
			}
		}// Fin rechPeriodique
		
		/**
		 * Accès à un ouvrage par son auteur
		 * Invoqué dans VueRechercherParAuteur
		 * @param nomAuteur
		 * @return l'ouvrage correspondant à l'auteur désigné
		 * affiche un message d'erreur si il n'y a pas d'ouvrage pour cet auteur
		 */
		public HashMap<String, Ouvrage> rechOuvrageParAuteur(String nomAuteur) {
			HashMap<String, Ouvrage> ouv = null;
			HashMap<String, Article> art = null;
			if (this.getVue() instanceof VueRechercherParAuteur) {
				ouv = this.auteurs.get(nomAuteur).getOuvrages();
				art = this.auteurs.get(nomAuteur).getArticles();
				this.getVue().setEtat(Vue.finale);
				((VueRechercherParAuteur)this.getVue()).alimenteExemplaires(ouv);
				((VueRechercherParAuteur)this.getVue()).alimenteArticles(art);
			}
			return ouv;
		} // Fin rechOuvrageParAuteur
		
		
		/**
		 * Accès à un lecteur par son numéro de lecteur
		 * Invoqué dans VueConsultLecteur
		 * @param numLecteur
		 * @return le lecteur correspondant
		 * affiche un message d'erreur si le lecteur n'est pas trouvé
		 */
		public Lecteur rechLecteur(String numLecteur) {
			Lecteur lecteur = this.getLecteur(numLecteur);
			Message dialog;
			if( lecteurs.size() == 0)
			{
				 dialog = new Message("Aucun lecteur enregistré !");
			}			
			else if (lecteur == null && lecteurs.size() != 0) {
				 dialog = new Message("Lecteur inconnu");
			}
			else {
				HashMap<Integer, Emprunt> emprunt = lecteur.getEmprunt();
				HashMap<Integer, Reservation> res = lecteur.getReservations();
				if (this.getVue() instanceof VueConsulterLecteur) {
					lecteur.addObserver(this.getVue());
					this.getVue().setEtat(Vue.finale);
					((VueConsulterLecteur)this.getVue()).alimenteLecteur(lecteur);
					((VueConsulterLecteur)this.getVue()).alimenteEmprunt(emprunt);
					((VueConsulterLecteur)this.getVue()).alimenteReservation(res);
				}
				if(this.getVue() instanceof VueResOuvrage){
						//lecteur.addObserver(this.getVue());
						this.getVue().setEtat(Vue.finale);
						((VueResOuvrage)this.getVue()).alimenteLec(lecteur, quota);
						((VueResOuvrage)this.getVue()).alimenteIsbn();
						}
				else if(this.getVue() instanceof VueEmpruntExemplaire){
					if (getLecteur(numLecteur).getNbEmprunts()-quota.getMaxEmprunt()!=0){
						((VueEmpruntExemplaire)this.getVue()).alimenteQuota(quota.getMaxEmprunt()-getLecteur(numLecteur).getNbEmprunts());
						this.getVue().setEtat(Vue.inter1);
					}
					else{
						dialog = new Message("Quota d'emprunts maximum atteint pour ce lecteur");
						fermerVue(this.getVue());
					}
				}
				else if (this.getVue() instanceof VueEmpruntExemplaireReserve){
					if (getLecteur(numLecteur).getNbEmprunts()<=quota.getMaxEmprunt()){
						((VueEmpruntExemplaireReserve)this.getVue()).alimenteEmpRes(lecteur);
						this.getVue().setEtat(Vue.inter1);
						if(((VueEmpruntExemplaireReserve)getVue()).getComboBox().getItemCount()==0){
							dialog = new Message("Aucune réservation pour ce lecteur");
						}
					}
					else{
						dialog = new Message("Quota d'emprunts maximum atteint pour ce lecteur");
						fermerVue(this.getVue());
					}
				}
			}
			return lecteur;
		}// Fin rechLecteur
		
		
	public void ajouterEmprunt(String isbn, String numExemplaire, String numLecteur){
			Message dialog;
			GregorianCalendar dateDebut = new GregorianCalendar();
			GregorianCalendar validite = dateDebut;
			validite.add(dateDebut.DATE,quota.getDuree());

			if(getEmprunts().get(isbn+numExemplaire) == null){
				if (getOuvrage(isbn) != null){
					if (getOuvrage(isbn).getExemplaire(Integer.valueOf(numExemplaire)) != null){
						if(getOuvrage(isbn).getExemplaire(Integer.valueOf(numExemplaire)).getStatut()== 0 ||
								getOuvrage(isbn).getExemplaire(Integer.valueOf(numExemplaire)).getStatut()== 4){
							Emprunt emprunt = new Emprunt(emprunts.size()+1, dateDebut, validite, getLecteur(numLecteur), getOuvrage(isbn).getExemplaire(Integer.valueOf(numExemplaire)));
					//Ajout de l'emprunt aux emprunts du lecteur
					getLecteur(numLecteur).setEmprunt(emprunt);
					//... Au dico du controleur
					setEmprunt(emprunt, emprunts.size()+1);
					//
					Exemplaire exp = getOuvrage(isbn).getExemplaire(Integer.valueOf(numExemplaire));
					exp.setEmprunt(emprunt);
					//
					//...Et met l'exemplaire emprunt à "emprunt" (statut = 1)
					
			
				getOuvrage(isbn).getExemplaire(Integer.valueOf(numExemplaire)).setStatut(2);
				dialog = new Message ("L'exemplaire a été emprunté");
						}
						else{
							 dialog = new Message ("L'exemplaire n'est pas empruntable");
						}
					}
					else
					{
						 dialog = new Message ("L'exemplaire n'existe pas");
					}
				}
				else
				{
					 dialog = new Message ("L'ouvrage n'existe pas");
				}
				
			}			

			else
			{
				 dialog = new Message ("L'exemplaire a déjà été emprunté");
			}		
	} //Fin ajouterEmprunt
	
	public void ajouterEmpruntReserve(Reservation res, String numLecteur){
		
		HashMap<Integer, Exemplaire> exemplaires = res.getOuvrage().getExemplaireDico();
		Exemplaire exemplaireAEmprunter;
		int i = 1;
		
		while(exemplaires.get(i).getStatut() 
				!= 4) {
			i++;
		}
		
		exemplaireAEmprunter = exemplaires.get(i);
		reservations.remove(res.getNumero());
		lecteurs.get(numLecteur).getReservations().remove(res.getNumero());
		ajouterEmprunt(res.getOuvrage().getIsbn(), String.valueOf(exemplaireAEmprunter.getNumero()), numLecteur);
		fermerVue(getVue());
	}
		
		public void retourExemplaire(String isbn, String numExemplaire){
		if ((isbn.length() != 0) || (numExemplaire.length() != 0)){	
			if(getEmprunts().get(Integer.valueOf(numExemplaire)) != null){
				// On met l'exemplaire dispo
				GregorianCalendar dateretour = new GregorianCalendar();
				GregorianCalendar datelimite = getEmprunts().get(Integer.valueOf(numExemplaire)).getDateLimite();
				
				
					if (getOuvrage(isbn).getExemplaire(Integer.valueOf(numExemplaire)).getStatut() ==2){
						getOuvrage(isbn).getExemplaire(Integer.valueOf(numExemplaire)).setStatut(0);
					}
					else if(getOuvrage(isbn).getExemplaire(Integer.valueOf(numExemplaire)).getStatut() ==3){
						getOuvrage(isbn).getExemplaire(Integer.valueOf(numExemplaire)).setStatut(4);
					}
				
					
				// On enlève l'emprunt de l'ensemble des emprunts
				Emprunt emprunt =getEmprunts().get(Integer.valueOf(numExemplaire));
				emprunts.remove(emprunt.getNumero());
				//On enlève l'emprunt du lecteur
				emprunt.getLecteur().retirerEmprunt(emprunt);
				// Et on supprime l'emprunt
				if(datelimite.before(dateretour)){
					int diff_de_mois = datelimite.MONTH - dateretour.MONTH;
					int diff_anne = datelimite.YEAR - dateretour.YEAR;
					int diff_jour = datelimite.DAY_OF_MONTH - dateretour.DAY_OF_MONTH;
					int prix = 0;
					
					if(diff_anne != 0){
						prix = prix + (diff_anne * getQuota().getPenalite());
					}
					else if(diff_de_mois !=0){
						prix = prix + (diff_de_mois * getQuota().getPenalite());
					}
					else if(diff_jour !=0){
						prix = prix + (diff_jour * getQuota().getPenalite());
					}
					
				Message dialog = new Message ("L'exemplaire est retourné en retard penalite : " + prix +" euros");
				
				}
				else{
				Message dialog = new Message ("L'exemplaire a été retourné");
				}
			fermerVue((VueRetourExemplaire)getVue());
				}
				
			else{
				System.out.println(getEmprunts().get(Integer.valueOf(numExemplaire)));
				if(getOuvrage(isbn)==null || getOuvrage(isbn).getExemplaire(Integer.valueOf(numExemplaire))==null){
				Message dialog = new Message ("L'exemplaire n'existe pas");
				}
				else{
				Message dialog = new Message ("L'exemplaire a déjà été retourné");
				fermerVue((VueRetourExemplaire)getVue());
				}
			}
		}
		else{
			
			Message dialog = new Message ("Tous les champs sont obligatoires");
			
		}
			
		}
		
		/**
		 * Création d'un lecteur
		 * Invoqué dans VueSaisieLecteur
		 */
		public void nouveauLecteur(String nom, String prenom, String adresse, String tel) {
			//vérification de la présence des informations
			Message dialog;
			if ((nom.length() == 0) || (prenom.length() == 0) || (adresse.length() == 0) || (tel.length() == 0)) {
				dialog = new Message ("Vous devez renseigner tous les champs");
			}
			else if(!isTelephone(tel))
			{
				dialog = new Message("Le champ téléphone ne doit contenir que 10 chiffres" );
			}
			else {
				int nblect=lecteurs.size()+1;
				Lecteur lecteur = new Lecteur(""+nblect, nom, prenom, adresse, tel);
				this.setLecteur(lecteur, ""+nblect);
				dialog = new Message("Le lecteur numero "+ nblect + " a été enregistré");
				this.fermerVue(this.getVue());
			}
		} //Fin nouveauLecteur
		
		/** Frederic Blanc
		 *  Methode pour Cu1
		 * @param maxEmprunt
		 * @param penalite
		 * @param valRes
		 * @param maxRes
		 * @param dureEmprunt
		 * @return
		 */
		public void nouvQuota(String maxEmprunt, String penalite, String valRes, String maxRes, String dureEmprunt)
		{
			Quota q = new Quota();
			Message dialog;
			if(maxEmprunt.length() == 0 || penalite.length() == 0 || valRes.length() == 0 || maxRes.length() == 0 ||
			   dureEmprunt.length() == 0)
			{
				 dialog = new Message("Tous les champs sont obligatoires");
			}
			else if(!isInteger(maxEmprunt) || !isInteger(penalite)|| !isInteger(valRes) || !isInteger(maxRes) || !isInteger(dureEmprunt) )
			{
				dialog = new Message("les champs doivent être remplie par des chiffres uniquement" );
			}
			else{
				
				int maxE  = Integer.valueOf(maxEmprunt);
				int maxR  = Integer.valueOf(maxRes);
				int dureE = Integer.valueOf(dureEmprunt);
				int penal = Integer.valueOf(penalite);
				int valR  = Integer.valueOf(valRes);
				if(maxE < 0 || maxR < 0 || dureE <0 || penal < 0 || valR < 0){
					 dialog = new Message("Valeur négative interdite" );
				}
				else
				{
				q.SetQuota(maxE, maxR, penal, valR, dureE);
				setquota(q);
				
				this.getVue().setEtat(Vue.finale);
				dialog = new Message( "Quota enregistré" );
				this.fermerVue (this.getVue());			
				}
			}
		}
		/** Frederic Blanc 
		 * Fonction qui verifie si le champ est bien remplie par un entier, retourne faux sinon
		 * @param ch
		 * @return
		 */
		private boolean isInteger(String ch)
		{
			boolean test = true;
			char[] tab = ch.toCharArray();
			for(char car : tab)
			{
				if(!Character.isDigit(car) && test)
				{
					test = false;
				}
			}
			return test;		
		}
		/** Johanna Loville 
		 * Fonction qui verifie si le champ téléphone est bien remplie
		 * @param ch
		 * @return
		 */
		private boolean isTelephone(String ch)
		{
			boolean test = true;
			int i = 0; 
			char[] tab = ch.toCharArray();
			for(char car : tab){
				if(isInteger(ch)){
					i++;
				}
				else{
					test = false;
				}
			}
				if(i!=10){
					test = false;
				}

			return test;		
		}
		/** Frederic Blanc 
		 *  Methode pour Cu10
		 *  Methode pour reservé un ouvrage emprunté avec test d'erreur
		 * @param numL
		 * @param isbn
		 * @param num
		 */
		public void resOuvrage(String numL, String isbn){
			GregorianCalendar dateDebut = new GregorianCalendar();
			GregorianCalendar validite = dateDebut;
			boolean reservable = true;
			Message dialog, Dialog;
			if(numL.length() == 0 || isbn.length() == 0){ 					//Test sur les Champ vide
				 dialog = new Message("Tous les champs sont obligatoires"); 
			}
			else if(Integer.valueOf(numL) <= 0 ||Integer.valueOf(isbn) <= 0)
			{
				dialog = new Message("les numeros ne peuvent pas être négatif");
			}
			else{

				validite.add(dateDebut.DATE,quota.getValiditeRes());		//On Modifie la date de validite a partir du jour ou la reservation est faite qui est la date du jour.
				Ouvrage ouv = getOuvrage(isbn);
				if(ouv.getNbExemplairesEmpruntable() != 0)					//Test pour savoir si il reste des exemplaire empruntable
				{
					Dialog = new Message("Il reste des exemplaires empruntables, inutile de réserver");
				}
				else
				{
					Lecteur lec = getLecteur(numL);
					HashMap<Integer, Emprunt> emp = lec.getEmprunt();
					if(quota.getMaxReservation()-lec.getNbReservations() > 0) 	//Test pour verifier si on peut emprunté 
					{
						Exemplaire exp = ouv.getExemplaireEmprunte(ouv.getExemplaireDico());
						for(int i=1; i < emp.size()+1;i++)
						{
							Emprunt empr = emp.get(i);
							if(empr.getExemplaire() != null && empr.getExemplaire() == exp)
							{
								reservable = false;
							}	
						}
						if(exp == null)											// Si aucun exemplaire n'est pas reservable
						{
							Dialog = new Message("Tous les exemplaires sont déjà reservés");
						}	
						else if(reservable == false){
							Dialog = new Message("Le lecteur à déjà emprunté cette ouvrage");
						}
						else													// sinon on modifie les donné et on confirme
						{
							exp.setStatut(3);
							Reservation res = new Reservation(dateDebut,validite,reservations.size(), ouv, lec);
							setReservation(res, reservations.size());
							lec.setReservation(res);
							Dialog = new Message("Réservation enregistrée");
						}						
					}
					else
					{
						Dialog = new Message("Votre quota de réservation est dépassé");
					}

				}	
				this.fermerVue (this.getVue());		
			}
		} 
		
		/**
		 * Création d'un exemplaire d'ouvrage 
		 * Invoqué dans VueSaisieExemplaire
		 * @param ouv l'ouvrage  dateRecep la date de réception de l'exemplaire	
		 * affiche un message de confirmation après l'enregistrement ou un message d'erreur 
		 */
		public void nouvExemplaire(Ouvrage ouv, String dateReception, String statut) {
			// vérification de la présence de la date et de son format
			Message dialog;
			if (dateReception.length() == 0 ){
					dialog = new Message("La date de réception est obligatoire");
					}
			else {
				GregorianCalendar date = ESDate.lireDate (dateReception);
				if (date == null) {
					dialog = new Message("Le format de la date est incorrect");
					}
				else {
					int statutEx;
					if (statut == "empruntable") {
						statutEx = Exemplaire.EMPRUNTABLE ; }
					else {
						statutEx = Exemplaire.EN_CONSULTATION ; }
						// demande d'ajout de l'exemplaire
						Exemplaire exemplaire = ouv.ajouterExemplaire(date, statutEx);
						// l'opération s'est bien passée
					if (exemplaire != null) {
						// le contrôleur modifie l'état de la vue
						this.getVue().setEtat(Vue.finale);
						// affichage d'un message de confirmation
						dialog = new Message("Exemplaire enregistré");
					}
					else {
						dialog = new Message("Date de réception incorrecte à la date d'édition.");
					}
				}
			}
		} // Fin nouvExemplaire
		

		public void nouvPeriodique(String nomPeriodique, String issn){
			Message dialog;
			if(nomPeriodique.length() == 0 || issn.length() == 0){
				dialog = new Message("Tous les champs sont obligatoires");
			}
			else{
				if (getPeriodique(issn)== null){
				Periodique periodique = new Periodique(nomPeriodique, issn);
				this.setPeriodique(periodique, issn);
				dialog = new Message("Périodique correctement créé");
				fermerVue((VueSaisiePeriodique)getVue());
			}
			else{
				dialog = new Message("Périodique déjà existant");
			}
			}
		} //Fin nouvPeriodique
		
		public void nouvParution(String issn,String ident, String titre){
			if(ident.length() == 0 || titre.length() == 0){
				Message dialog = new Message("Tous les champs sont obligatoires");
			}
			else {
			
				
				if(getPeriodique(issn).getParution(ident)==null){
				this.getVue().setEtat(Vue.finale);	
				if(((VueSaisieParution)getVue()).getComboBox().getItemCount() == 0){
					((VueSaisieParution)getVue()).getComboBox().setEnabled(false);
			}
				if(titre.length() == 0) {
					Message dialog = new Message("Tous les champs sont obligatoires");
				}
				Parution parution = new Parution(ident, titre);
				getPeriodique(issn).getParutions().put(ident, parution);
				getPeriodique(issn).incrementeParution();
			}
			else{
				Message dialog = new Message("Parution déjà existante");
			}
			}
		} //Fin nouvParution
		

		
		public void ajoutArticle(Auteur aut, String titre, String issn, String ident){
//			Auteur aut = new Auteur("","");
			Message dialog;
			aut.addObserver(this.getVue());
			String cleAuteur = aut.getNom()+" "+aut.getPrenom();
			if (this.getPeriodique(issn).getParution(ident).getArticle(titre+cleAuteur)==null){
				if(this.getAuteur(cleAuteur) == null){
					setAuteur(aut, cleAuteur);
					aut.notifierObservateurs();
				}
				Article article = new Article(titre, this.getAuteur(cleAuteur), this.getPeriodique(issn).getParution(ident));
				this.getPeriodique(issn).getParution(ident).ajoutArticle(article);
				this.getAuteur(cleAuteur).setArticle(article);
				dialog = new Message("Article " + titre + " enregistré dans " + this.getPeriodique(issn).getParution(ident).getTitre());
				
			}
			else {
				dialog = new Message("Article déjà existant");
			}
		}// Fin ajoutArticle
		

		
		/**
		 * Création d'un  d'ouvrage 
		 * Invoqué dans VueSaisieOuvrage
		 * @param  dateEdition la date d'édition de l'ouvrage
		 * affiche un message de confirmation après l'enregistrement ou un message d'erreur 
		 */
		public void nouvOuvrage(String isbn, String titre, String nauteur, String pauteur, String editeur, String dateEdition) {
			// vérification de la présence des infos obligatoires et du format de la date
			Message dialog;
			if ((isbn.length() == 0) || (titre.length() == 0) || (nauteur.length() == 0) || (pauteur.length() == 0)
					|| (editeur.length() == 0 )|| (dateEdition.length() == 0 )){
					dialog = new Message("Tous les champs sont obligatoires");
					}
			else {
				GregorianCalendar date = ESDate.lireDate (dateEdition);
				if (date == null) {
					dialog = new Message("Le format de la date est incorrect");
					}
				else if (this.getOuvrage(isbn )== null) {
					Auteur auteur = getAuteur(nauteur+pauteur);
					if (auteur== null ){
						auteur = new Auteur(nauteur,pauteur);
						setAuteur(auteur, nauteur+" "+pauteur);
					}
				// Instanciation de l'ouvrage
					Ouvrage ouvrage = new Ouvrage(isbn, titre, nauteur, pauteur, editeur, date);
				// Ajout de l'ouvrage dans l'ensemble des ouvrages de la bibliothèque
					auteur.addOuvrage(ouvrage);
					this.setOuvrage(ouvrage, isbn);
					
					dialog = new Message("Ouvrage enregistré");
					this.fermerVue (this.getVue());
					} 
					else {
						 dialog = new Message("Ouvrage déjà présent");
					}
				}
			}
		} // Fin nouvOuvrage